home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / GameKit / gamekit-1 / GameView.m < prev    next >
Text File  |  1995-06-12  |  11KB  |  435 lines

  1.  
  2. #import <gamekit/gamekit.h>        // Colors
  3. #import <daymisckit/daymisckit.h>    // ExtendedApp, etc.
  4. #import <dpsclient/psops.h>        // PSsetgray()
  5. #import <dpsclient/wraps.h>        // PScompositerect()
  6. #import <libc.h>                // for random(), etc.
  7. #import <math.h>                // for floor(), etc.
  8. #import <stdio.h>                // for standard C file operations
  9.  
  10.  
  11. @implementation GameView
  12.  
  13. #define dragdef const char *dragTypes[3] =\
  14.         {NXFilenamePboardType, NXColorPboardType, NULL}
  15. #define dragNum    2
  16.  
  17. - initFrame:(const NXRect *)frm    // designated initializer for a view
  18. {
  19.     dragdef;
  20.     
  21.     [super initFrame:frm];
  22.     cycles = 0;
  23.     srandom(time(0));
  24.     demoMode = NO;
  25.     grayBorder = YES;
  26.     state = GAMEOVER;
  27.     demoWait = 0;
  28.     doingBorder = NO;
  29.     grayBorder = YES;
  30.     backColor = NXConvertRGBToColor(0.333, 0.333, 0.333); // dark gray default
  31.     backIsColor = YES; // default bg is dark gray...
  32.     [self registerForDraggedTypes:dragTypes count:dragNum];
  33.     dragOperation = NX_DragOperationNone;
  34.     return self;
  35. }
  36.  
  37. - appDidInit:sender        // forwarded by gamebrain
  38. {
  39.     if (!controller) controller = [NXApp delegate];
  40.     if (!preferences) preferences = [controller preferencesBrain];
  41.     if (!scoreKeeper) scoreKeeper = [controller scoreKeeper];
  42.     if (!strings) strings = [controller mainStrings];
  43.     if (!customSound) customSound = [controller soundPlayer];
  44.     [self loadPix];
  45.     return self;
  46. }
  47.  
  48. - loadPix
  49. {
  50.     const char *tmpStr;
  51.     char *okStr; float r, g, b;
  52.     
  53.     [self allocateGState];
  54.     
  55. // set background
  56.     okStr = malloc(8);
  57.     tmpStr = NXGetDefaultValue([NXApp appName], "BackColor");
  58.     if (tmpStr) {
  59.         backIsColor = NO;
  60.         sscanf(tmpStr, "%s %f %f %f", &okStr[0], &r, &g, &b);
  61.         backColor = NXConvertRGBToColor(r, g, b); 
  62.         if (okStr[0] == 'Y') {
  63.             backIsColor = YES;
  64.         }
  65.     }
  66.     free(okStr);
  67.     
  68.     // get some buffers to hold our drawings.
  69.     buffer = [[NXImage allocFromZone:[self zone]] initSize:&bounds.size]; 
  70.     staticBuffer = [[NXImage allocFromZone:[self zone]] initSize:&bounds.size];
  71.      
  72.     if (!backIsColor)
  73.         [self setBackgroundFile:
  74.                 NXGetDefaultValue([NXApp appName], "BackGround")
  75.             andRemember:NO];
  76.     
  77.     return self;
  78. }
  79.  
  80. - animate:sender
  81. {        // method to start the animation - called by appDidInit
  82.  
  83.     // set up Animator: (autoUpdate)  this handles moving viruses and
  84.     //   makes sure the columns fall when they should.  The animator is
  85.     //   an object that handles timed entries "smartly".
  86.     animator = [[Animator alloc] initChronon:[self speedTime]
  87.             adaptation:0.0   target:self
  88.             action:@selector(autoUpdate:) autoStart:YES eventMask:0];
  89.     
  90.     return self;
  91. }
  92.  
  93. - (BOOL)demoMode            // if last game was demo
  94. { return demoMode; }
  95.  
  96. - (float)speedTime        // returns time between animation frames
  97. {  return GRANULARITY;    // return delay between clock ticks
  98. }            // 0.05 is about as fast as should be used.
  99.  
  100. - (int)gameState    // tell caller our state... if in demo, game is over
  101. { if (demoMode) return GAMEOVER; return state; }
  102.  
  103. - (int)realGameState    // tell caller our state...may need to really know...
  104. { return state; }
  105.  
  106. - getOffset:(NXPoint *)aPoint    // returns offset by reference
  107. {
  108.     GK_VECTOR_X(aPoint) = offset.x; GK_VECTOR_Y(aPoint) = offset.y;
  109.     return self;
  110. }
  111.  
  112. - setOffset:(const NXPoint *)aPoint    // change the offset
  113. {
  114.     offset.x = GK_VECTOR_X(aPoint); offset.y = GK_VECTOR_Y(aPoint);
  115.     return self;
  116. }
  117.  
  118. - autoUpdate:sender    // called by timed entry to update screen periodically
  119. {            // ALL animation is controlled from here!!!
  120.     cycles++;
  121.     // you would do updates to various screen objects and
  122.     // then do a [self updateSelf:&bounds :1];
  123.     return self;
  124. }
  125.  
  126. - updateSelf:(NXRect *)rects :(int)rectCount    // redraws the screen.
  127. {        // it redraws only what has changed since last redraw.
  128.     NXPing();
  129.     return self;
  130. }
  131.  
  132. - mouseDown:(NXEvent *)event        // handle mouseDown events.
  133. {
  134.     [controller pauseGame:self];    // pause/unpause game
  135.     return self;
  136. }
  137.  
  138. - (BOOL)acceptsFirstMouse        // let us grab activating mousedowns
  139. {    // 1st click is to become 1st responder, NOT pause/unpause
  140.     return NO;
  141. }
  142.  
  143. - setKey:(int)keyIndex val:(char)keyVal        // change key we respond to
  144. {
  145.     keys[keyIndex] = keyVal;
  146.     return self;
  147. }
  148.  
  149. - pause:sender                // set pause status.  
  150. {
  151.     paused = YES;
  152.     return self;
  153. }
  154.  
  155. - unpause:sender            // remove paused status
  156. {
  157.     paused = NO;
  158.     return self;
  159. }
  160.     
  161. - (BOOL)isPaused            // tell caller is we're paused
  162. { return paused; }
  163.  
  164. - keyDown:(NXEvent *)myevent        // handle keyDown events.
  165. {
  166.     PSobscurecursor();  // subclasses which override need to do this.
  167.     if (myevent->data.key.charSet == NX_ASCIISET &&
  168.         (myevent->flags&(NX_CONTROLMASK|NX_ALTERNATEMASK|NX_COMMANDMASK)) == 0)
  169.     {    
  170.         if (GKKEYCODE == 'p') { // allow pause
  171.             if (paused) [controller unpause];
  172.             else [controller pause];
  173.         } else if (GKKEYCODE == 'n') { // allow new game
  174.             [controller startNewGame:self]; // re-start the game
  175.             // returns nil if user changes mind...
  176.         } else if (paused) {    // any keyDown unpauses game (except 'p').
  177.             [controller unpause];
  178.         }
  179.     } else return [super keyDown:myevent];
  180.     return self;
  181. }
  182.  
  183. - (BOOL)acceptsFirstResponder        // to grab keyboard events
  184. { return YES; }
  185.  
  186. - getPreferences
  187. {
  188.     if (!preferences) preferences = [[NXApp delegate] preferencesBrain];
  189.     return self;
  190. }
  191.  
  192. - free                    // get rid of support objects
  193. {
  194.     [animator free];
  195.     return [super free];
  196. }
  197.  
  198. - setUpScreen
  199. {        
  200.     if ((demoMode)||(doingBorder)) [self display];
  201.     return self;
  202. }
  203.  
  204. - changeBorder:(BOOL)borderOn
  205. { // move view about in the window & do sizing
  206.     NXRect wFrame;
  207.     
  208.     if (borderOn == grayBorder) return self;
  209.     
  210.     if (borderOn) {
  211.         [window getFrame:&wFrame];
  212.         NXInsetRect(&wFrame, -BEZELSIZE, -BEZELSIZE);
  213.         [self moveBy:BEZELSIZE :BEZELSIZE];
  214.         [window placeWindowAndDisplay:&wFrame];
  215.     } else {
  216.         [window getFrame:&wFrame];
  217.         NXInsetRect(&wFrame, BEZELSIZE, BEZELSIZE);
  218.         [self moveBy:-BEZELSIZE :-BEZELSIZE];
  219.         [window placeWindowAndDisplay:&wFrame];
  220.     }
  221.     grayBorder = borderOn;
  222.     return self;
  223. }
  224.  
  225. - restartGame
  226. {
  227.     cycles = 0;
  228.     state = NORMALSTATE;
  229.     if (demoMode) {
  230.         demoMode = NO;
  231.         [[self window] setTitle:[strings valueForStringKey:"GameName"]];
  232.     }
  233.     [scoreKeeper resetScore];
  234.     [self getPreferences]; // make sure we're up to date
  235.     return self;
  236. }
  237.  
  238. //// Background handling methods stolen from BreakApp:
  239.  
  240. - setBackgroundFile:(const char *)fileName andRemember:(BOOL)remember
  241. // This methods allows changing the file used to paint the background of the
  242. // playing field. Set fileName to NULL to revert to the default. Set
  243. // remember to YES if you wish the write the value out in the defaults.
  244. {
  245.     [backGround free];
  246.  
  247.     backGround = [[NXImage allocFromZone:[self zone]] initSize:&bounds.size];
  248.     [backGround setBackgroundColor:backColor];
  249.     [backGround setScalable:YES];
  250.     if (fileName) {
  251.         [backGround useFromFile:fileName];
  252.         if (remember) {
  253.             NXWriteDefault ([NXApp appName], "BackGround", fileName);
  254.         }
  255.     } else { // default background image
  256.         [backGround useFromSection:"BackGround.eps"];
  257.         if (remember) {
  258.             NXRemoveDefault ([NXApp appName], "BackGround");
  259.         }
  260.     }
  261.     backIsColor = NO;
  262.     [self buildBackground];
  263.     [self writeColor];
  264.     [self display];
  265.     return self;   
  266. }
  267.  
  268. - buildBackground { return self; }    // for subclass use
  269.  
  270. // The following two methods allow changing the background image from
  271. // menu items or buttons.
  272.  
  273. - changeBackground:sender
  274. {
  275.     const char *const *types = [NXImage imageFileTypes];  
  276.     if ([[OpenPanel new] runModalForTypes:types]) {
  277.         [self setBackgroundFile:[[OpenPanel new] filename] andRemember:YES];
  278.         [self display];
  279.     }
  280.     return self;
  281. }
  282.  
  283. - revertBackground:sender
  284. {
  285.     backIsColor = NO;
  286.     [self setBackgroundFile:NULL andRemember:YES];
  287.     [self display];
  288.     return self;
  289. }
  290.  
  291. - loadAnImage:(const char *)imageName
  292. {
  293.     char *tempStr = (char *)malloc(MAXPATHLEN);
  294.     sprintf(tempStr, "%s/%s", [NXApp appDirectory], imageName);
  295.     [self setBackgroundFile:tempStr andRemember:YES];
  296.     free(tempStr); [self display];
  297.     return self;
  298. }
  299.  
  300. - back1:sender { return [self loadAnImage:"Back1.eps"]; }
  301. - back2:sender { return [self loadAnImage:"Back2.tiff"]; }
  302. - back3:sender { return [self loadAnImage:"Back3.tiff"]; }
  303.  
  304. - drawBackground:(NXRect *)rect
  305. // drawBackground: just draws the specified piece of the background by
  306. // compositing from the background image.
  307. {
  308.     NXRect tmpRect = *rect;
  309.  
  310.     if (backIsColor) {
  311.         NXSetColor(backColor);
  312.         NXRectFill(rect);
  313.         return self;
  314.     }
  315.     
  316.     NX_X(&tmpRect) = floor(NX_X(&tmpRect));
  317.     NX_Y(&tmpRect) = floor(NX_Y(&tmpRect));
  318.     if (NXDrawingStatus == NX_DRAWING) {
  319.         PSsetgray (NX_BLACK);
  320.         PScompositerect (NX_X(&tmpRect), NX_Y(&tmpRect),
  321.             NX_WIDTH(&tmpRect), NX_HEIGHT(&tmpRect), NX_SOVER);
  322.     }
  323.     [backGround composite:NX_SOVER fromRect:&tmpRect toPoint:&tmpRect.origin];
  324.     return self;
  325. }
  326.  
  327. - sizeTo:(NXCoord)width :(NXCoord)height 
  328. {
  329.     [super sizeTo:width :height];
  330.     [backGround setSize:&bounds.size];
  331.     return self;
  332. }
  333.  
  334.  
  335. // deal with drag and drop colors:
  336. - acceptColor:(NXColor)color atPoint:(const NXPoint *)aPoint
  337. {
  338.     backIsColor = YES;
  339.     backColor = color;
  340.     [[self writeColor] update];
  341.     return self;
  342. }
  343.  
  344. - writeColor
  345. {
  346.     char def[256];
  347.     float r, g, b;
  348.     
  349.     NXConvertColorToRGB(backColor, &r, &g, &b);
  350.     sprintf(def, "%s %f %f %f", (backIsColor ? "YES" : "NO"), r, g, b);
  351.     NXWriteDefault ([NXApp appName], "BackColor", def);
  352.     return self;
  353. }
  354.  
  355.  
  356. // these assume that you already locked focus.  Thus, when overriding
  357. // these methods, the subclas should lock focus in the static buffer
  358. // before calling the super (this) method.
  359. - rebuildStaticBuffer
  360. {
  361.     [self drawBackground:&bounds];
  362.     return self;
  363. }
  364.  
  365. - rebuildStaticAt:(NXRect *)rect
  366. {
  367.     [self drawBackground:rect];
  368.     return self;
  369. }
  370.  
  371. // drag and drop an image into the view's background.
  372. // uses 3.0 drag kit stuff
  373.  
  374. - (NXDragOperation)draggingEntered:sender
  375. {
  376.     NXDragOperation sourceMask;
  377.  
  378.     // Ask the sender for its operation mask.
  379.     sourceMask = [sender draggingSourceOperationMask]; 
  380.     if (sourceMask & NX_DragOperationCopy)
  381.         dragOperation = NX_DragOperationCopy;
  382.     else if (sourceMask & NX_DragOperationGeneric)
  383.         dragOperation = NX_DragOperationGeneric;
  384.     else dragOperation = NX_DragOperationNone;
  385.     return dragOperation;
  386. }    
  387.  
  388. - (NXDragOperation)draggingUpdated:sender { return dragOperation; }
  389. - draggingExited:sender { return self; }
  390.  
  391. - (BOOL)prepareForDragOperation:sender
  392. { // We do want to accept the dragged image/color.
  393.     return YES;
  394. }
  395.     
  396. - (BOOL)performDragOperation:sender
  397. {
  398.     Pasteboard *dragPasteboard = [Pasteboard newName:NXDragPboard];
  399.     char *file;
  400.     int length;
  401.     dragdef;
  402.     BOOL foundOne = NO;
  403.  
  404.     if ([dragPasteboard findAvailableTypeFrom:dragTypes num:dragNum]
  405.             == NXFilenamePboardType) {
  406.         if ([dragPasteboard readType:NXFilenamePboardType
  407.                             data:&file length:&length]) {
  408.             foundOne = YES; 
  409.             [self setBackgroundFile:file andRemember:YES];
  410.             [dragPasteboard deallocatePasteboardData:file length:length];
  411.             [NXApp activateSelf:YES];
  412.             [window makeKeyAndOrderFront:self];
  413.     }    }
  414.     else if ([dragPasteboard findAvailableTypeFrom:dragTypes num:dragNum]
  415.             == NXColorPboardType) {
  416.         NXPoint p = [sender draggingLocation];
  417.         NXColor c = NXReadColorFromPasteboard([sender draggingPasteboard]);
  418.         [self acceptColor:c atPoint:&p];
  419.         foundOne = YES;
  420.         [NXApp activateSelf:YES];
  421.         [window makeKeyAndOrderFront:self];
  422.     }
  423.     return foundOne;
  424. }
  425.     
  426. - concludeDragOperation:sender { return self; }
  427.  
  428. - gameOver    // sent by GameBrain
  429. {
  430.     state = GAMEOVER;
  431.     return self;
  432. }
  433.  
  434. @end
  435.